﻿using BLL.Interface;
using Common;
using Common.Extensions;
using DAL.Interface;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Model;
using Model.DTO.Public.GetList;
using Model.DTO.Public.OperateId;
using Model.DTO.User;
using Model.Entity.Article.Relation;
using Model.Entity.Type;
using Model.Entity.User;
using Model.Entity.User.Relation;
using Model.Enum;
using System.Data;
using System.Security.Claims;

namespace BLL
{
    /// <summary>
    /// 用户业务逻辑层
    /// </summary>
    public class UserBLL : IUserBLL
    {
        private readonly IBaseDAL<TB_User> _userDAL;
        private readonly IBaseDAL<TB_UserType> _userTypeDAL;
        private readonly IBaseDAL<TB_UserToType> _userToTypeDAL;
        private readonly IBaseDAL<TB_StateType> _stateTypeDAL;
        private readonly IBaseDAL<TB_GenderType> _genderTypeDAL;
        private readonly IMemoryCache _memoryCache;
        private readonly JWTHelper _jWTHelper;
        public UserBLL(
            IBaseDAL<TB_User> userDAL,
            IBaseDAL<TB_UserType> userTypeDAL,
            IBaseDAL<TB_UserToType> userToTypeDAL,
            IBaseDAL<TB_StateType> stateTypeDAL,
            IBaseDAL<TB_GenderType> genderTypeDAL,
            IMemoryCache memoryCache,
            JWTHelper jwtHelper
            )
        {
            _userDAL = userDAL;
            _userTypeDAL = userTypeDAL;
            _userToTypeDAL = userToTypeDAL;
            _stateTypeDAL = stateTypeDAL;
            _genderTypeDAL = genderTypeDAL;
            _memoryCache = memoryCache;
            _jWTHelper = jwtHelper;
        }
        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<ResponseMessage> AddUser(AddUserDTO param)
        {
            try
            {
                #region 过滤
                var existUserType = await _userTypeDAL.GetEntityAllAsync(x => x.Id == param.UserTypeId).Result.AnyAsync();
                if (!existUserType)
                {
                    return ResponseMessage.CreateError("用户类型不存在");
                }
                if (param.GenderTypeId != null)
                {
                    var existGenderType = await _genderTypeDAL.GetEntityAllAsync(x => x.Id == param.GenderTypeId).Result.AnyAsync();
                    if (!existGenderType)
                    {
                        return ResponseMessage.CreateError("性别类型不存在");
                    }
                }
                var users = await _userDAL.GetEntityAllAsync();
                var existUserName = await users.Where(x => x.UserName == param.UserName).AnyAsync();
                if (existUserName)
                {
                    return ResponseMessage.CreateError("用户名已存在");
                }
                var existEmail = await users.Where(x => x.Email == param.Email).AnyAsync();
                if (existEmail)
                {
                    return ResponseMessage.CreateError("邮箱已存在");
                }
                if (param.PhoneNumber != null)
                {
                    var existPhoneNumber = await users.Where(x => x.PhoneNumber == param.PhoneNumber).AnyAsync();
                    if (existPhoneNumber)
                    {
                        return ResponseMessage.CreateError("手机号已存在");
                    }
                }
                #endregion
                var user = new TB_User();
                param.CopyPropertiesTo(user);
                #region 数据调整
                //二次密码加密(前端已进行一次加密)
                user.PasswordSalt = await Task.Run(() => SecurityHelper.GenerateSaltHex());
                user.Password = await Task.Run(() => SecurityHelper.SHA256Encrypt(user.PasswordSalt + param.Password));
                //默认头像设置
                if (string.IsNullOrEmpty(user.AvatarPath))
                {
                    user.AvatarPath = "DefaultAvatar.jpg";
                }
                #endregion
                using var tran = await _userDAL.BeginTransactionAsync();
                try
                {
                    user = await _userDAL.AddEntityAndReturnAsync(user);
                    var userToType = new TB_UserToType()
                    {
                        UserId = user.Id,
                        UserTypeId = user.UserTypeId,
                    };
                    await _userToTypeDAL.AddEntityAsync(userToType);
                    await tran.CommitAsync();
                    return ResponseMessage.CreateSuccess("添加成功");
                }
                catch
                {
                    await tran.RollbackAsync();
                    throw;
                }
            }
            catch
            {
                return ResponseMessage.CreateError("添加失败");
            }
        }
        /// <summary>
        /// 编辑用户
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<ResponseMessage> EditUser(EditUserDTO param)
        {
            try
            {
                #region 过滤
                var user = await _userDAL.GetEntityAllAsync(x => x.Id == param.Id).Result.FirstOrDefaultAsync();
                if (user == null)
                {
                    return ResponseMessage.CreateError("用户不存在");
                }
                var existUserType = await _userTypeDAL.GetEntityAllAsync(x => x.Id == param.UserTypeId).Result.AnyAsync();
                if (!existUserType)
                {
                    return ResponseMessage.CreateError("用户类型不存在");
                }
                var existStateType = await _stateTypeDAL.GetEntityAllAsync(x => x.Id == param.StateTypeId).Result.AnyAsync();
                if (!existStateType)
                {
                    return ResponseMessage.CreateError("状态类型不存在");
                }
                if (param.GenderTypeId != null)
                {
                    var existGenderType = await _genderTypeDAL.GetEntityAllAsync(x => x.Id == param.GenderTypeId).Result.AnyAsync();
                    if (!existGenderType)
                    {
                        return ResponseMessage.CreateError("性别类型不存在");
                    }
                }
                var elseUsers = await _userDAL.GetEntityAllAsync(x => x.Id != param.Id);
                var existEmail = await elseUsers.Where(x => x.Email == param.Email).AnyAsync();
                if (existEmail)
                {
                    return ResponseMessage.CreateError("邮箱已存在");
                }
                if (param.PhoneNumber != null)
                {
                    var existPhoneNumber = await elseUsers.Where(x => param.PhoneNumber != null && x.PhoneNumber == param.PhoneNumber).AnyAsync();
                    if (existPhoneNumber)
                    {
                        return ResponseMessage.CreateError("手机号已存在");
                    }
                }
                #endregion
                param.CopyPropertiesTo(user);
                var result = await _userDAL.EditEntityAsync(user);
                return result ? ResponseMessage.CreateSuccess("编辑成功") : ResponseMessage.CreateError("编辑失败");
            }
            catch
            {
                return ResponseMessage.CreateError("编辑失败");
            }
        }
        /// <summary>
        /// 获取用户列表
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<ResponseMessage> GetUserList(GetListDTO param)
        {
            try
            {
                #region 参数校验
                if (param.Page <= 0)
                {
                    param.Page = 1;
                }
                if (param.Size <= 0)
                {
                    param.Size = 10;
                }
                #endregion
                var users = await _userDAL.GetEntityAllAsync(x => x.UserName.Contains(param.Query ?? string.Empty)).Result.Select(x => new ReturnUserListDTO
                {
                    UserName = x.UserName,
                    Email = x.Email,
                    Id = x.Id,
                    CreatedDate = x.CreatedDate,
                    UserTypeId = x.UserTypeId,
                    StateTypeId = x.StateTypeId,
                    Remark = x.Remark,
                    PhoneNumber = x.PhoneNumber,
                    Statement = x.Statement,
                    SchoolName = x.SchoolName,
                    AvatarPath = x.AvatarPath,
                    BackdropPath = x.BackdropPath,
                    Birthday = x.Birthday,
                    LastLoginDate = x.LastLoginDate,
                    GenderTypeId = x.GenderTypeId
                }).ToListAsync();
                var userTypes = await _userTypeDAL.GetEntityAllAsync();
                var userToTypes = await _userToTypeDAL.GetEntityAllAsync();
                foreach (var user in users)
                {
                    var userToTypesOfUser = userToTypes.Where(x => x.UserId == user.Id);
                    var userTypeCodes = from userType in userTypes
                                        join userToType in userToTypesOfUser on userType.Id equals userToType.UserTypeId
                                        select userType.Code;
                    user.UserTypeCodes = userTypeCodes.ToList();
                }
                var total = users.Count;
                var list = users.Skip((param.Page - 1) * param.Size).Take(param.Size);
                return ResponseMessage.CreateSuccess("获取成功", new { total, list });
            }
            catch
            {
                return ResponseMessage.CreateError("获取失败");
            }
        }
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<ResponseMessage> Login(UserLoginDTO param)
        {
            try
            {
                #region 过滤
                //param.Captcha = param.Captcha.ToLowerInvariant();
                //var captcha = _memoryCache.Get<string>(param.AppId);
                //if (captcha == null || captcha.ToLowerInvariant() != param.Captcha)
                //{
                //    return ResponseMessage.CreateError("验证码错误");
                //}
                //_memoryCache.Remove(param.AppId);
                var user = await _userDAL.GetEntityAllAsync(x => x.UserName == param.UserName).Result.FirstOrDefaultAsync();
                if (user == null)
                {
                    return ResponseMessage.CreateError("用户不存在");
                }
                if (user.StateTypeId == (int)StateType.Ban)
                {
                    return ResponseMessage.CreateError("用户被封禁");
                }
                if (user.StateTypeId == (int)StateType.Cancel)
                {
                    return ResponseMessage.CreateError("用户已注销");
                }
                string encryptPassword = await Task.Run(() => SecurityHelper.SHA256Encrypt(user.PasswordSalt + param.Password));
                if (!user.Password.Equals(encryptPassword))
                {
                    return ResponseMessage.CreateError("密码错误");
                }
                #endregion
                var userToTypeIds = _userToTypeDAL.GetEntityAllAsync(x => x.UserId == user.Id).Result.Select(x => x.UserTypeId);
                List<string> userToTypeCodes;
                if (!await userToTypeIds.AnyAsync())
                {
                    userToTypeCodes = new List<string>() { UserType.User.ToString() };
                }
                else
                {
                    userToTypeCodes = await _userTypeDAL.GetEntityAllAsync(x => userToTypeIds.Contains(x.Id)).Result.Select(x => x.Code).ToListAsync();
                }
                #region 数据调整
                user.LastLoginDate = DateTime.Now;
                #endregion
                await _userDAL.EditEntityAsync(user);
                var userTokenDTO = new UserTokenDTO();
                user.CopyPropertiesTo(userTokenDTO);
                userTokenDTO.UserTypeCodes = userToTypeCodes;
                var jsonString = userTokenDTO.ToJson();
                var data = new { Token = _jWTHelper.GenerateJwtToken(jsonString, userToTypeCodes, 60 * 24) };
                return ResponseMessage.CreateSuccess("登录成功", data);
            }
            catch
            {
                return ResponseMessage.CreateError("登录失败");
            }
        }
        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<ResponseMessage> Register(UserRegisterDTO param)
        {
            try
            {
                #region 过滤
                param.Captcha = param.Captcha.ToLowerInvariant();
                var captcha = _memoryCache.Get<string>(param.Email);
                if (captcha == null || captcha.ToLowerInvariant() != param.Captcha)
                {
                    return ResponseMessage.CreateError("验证码错误");
                }
                _memoryCache.Remove(param.Email);
                #endregion
                var addUser = new AddUserDTO()
                {
                    UserTypeId = (int)UserType.User,
                };
                param.CopyPropertiesTo(addUser);
                addUser.Remark = "用户注册";
                var addResult = await AddUser(addUser);
                var result = addResult.Code == ResponseType.Success;
                return result ? ResponseMessage.CreateSuccess("注册成功") : ResponseMessage.CreateError("注册失败");
            }
            catch
            {
                return ResponseMessage.CreateError("注册失败");
            }
        }
        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task<ResponseMessage> GetUserInfo(string? token)
        {
            try
            {
                var jsonString = await Task.Run(() => _jWTHelper.TokenDecrypt(token, ClaimTypes.UserData));
                if (string.IsNullOrWhiteSpace(jsonString))
                {
                    return ResponseMessage.CreateError("Token无效");
                }
                var userTokenDTO = jsonString.ToObject<UserTokenDTO>();
                return ResponseMessage.CreateSuccess("获取成功", userTokenDTO);
            }
            catch
            {
                return ResponseMessage.CreateError("获取失败");
            }
        }
        /// <summary>
        /// 禁用用户
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<ResponseMessage> BanUser(OperateIdDTO_INT param)
        {
            try
            {
                if (param.Id > 0)
                {
                    param.Ids.Clear();
                    param.Ids.Add(param.Id);
                    param.Id = 0;
                    return await BanUser(param);
                }
                #region 过滤
                if (param.Ids.Count <= 0)
                {
                    return ResponseMessage.CreateError("Id无效");
                }
                #endregion
                using var tran = await _userDAL.BeginTransactionAsync();
                try
                {
                    foreach (var id in param.Ids)
                    {
                        var user = await _userDAL.GetEntityAllAsync(x => x.Id == id).Result.FirstOrDefaultAsync() ?? throw new();
                        user.StateTypeId = (int)StateType.Ban;
                        await _userDAL.EditEntityAsync(user);
                    }
                    await tran.CommitAsync();
                    return ResponseMessage.CreateSuccess("禁用成功");
                }
                catch
                {
                    await tran.RollbackAsync();
                    throw;
                }
            }
            catch
            {
                return ResponseMessage.CreateError("禁用失败");
            }
        }
        /// <summary>
        /// 绑定用户角色
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<ResponseMessage> BindUserTypes(OperateIdDTO_INT param)
        {
            try
            {
                var userToTypeIds = _userToTypeDAL.GetEntityAllAsync(x => x.UserId == param.Id).Result.Select(x => x.UserId);
                using var tran = await _userToTypeDAL.BeginTransactionAsync();
                try
                {
                    //解绑用户类型
                    foreach (var userToTypeId in userToTypeIds)
                    {
                        if (!param.Ids.Contains(userToTypeId))
                        {
                            await _userToTypeDAL.DeleteEntityAsync(userToTypeId);
                        }
                    }
                    //绑定用户类型
                    foreach (var id in param.Ids)
                    {
                        if (!userToTypeIds.Contains(id))
                        {
                            await _userToTypeDAL.AddEntityAsync(new TB_UserToType { UserId = param.Id, UserTypeId = id });
                        }
                    }
                    await tran.CommitAsync();
                    return ResponseMessage.CreateSuccess("绑定成功");
                }
                catch
                {
                    await tran.RollbackAsync();
                    throw;
                }
            }
            catch
            {
                return ResponseMessage.CreateError("绑定失败");
            }
        }
        /// <summary>
        /// 获取用户绑定的用户类型列表
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResponseMessage> GetUserBindUserTypes(int id)
        {
            try
            {
                var userToTypes = await _userToTypeDAL.GetEntityAllAsync(x => x.UserId == id);
                var total = userToTypes.Count();
                var list = await userToTypes.ToListAsync();
                return ResponseMessage.CreateSuccess("获取成功", new { total, list });
            }
            catch
            {
                return ResponseMessage.CreateError("获取失败");
            }
        }
    }
}
